#ifndef __MY_DATA__
#define __MY_DATA__
#include <unordered_map>
#include <pthread.h>
#include <vector>
#include "Util.hpp"
#include "Config.hpp"

namespace Cloud
{
    struct BackupInfo // 备份信息类
    {
    public:
        BackupInfo() {}
        BackupInfo(const string &filepath)
        {
            Cloud::FileUtil fu(filepath);
            Cloud::Config *config = Cloud::Config::GetInstance();
            if (fu.Exists() == false)
            {
                cout << "BackupInfo: file not exists" << endl;
                exit(-1);
            }
            pack_flag = false;
            packRunning = false;
            fsize = fu.FileSize();
            atime = fu.LastATime();
            mtime = fu.LastMTime();
            // realpath = config->GetBackDir() + fu.GetFileName();
            realpath = filepath;
            packpath = config->GetPackDir() + fu.GetFileName() + config->GetPackFileSuffix();
            url = config->GetDownLoadprefix() + fu.GetFileName();
        }
        BackupInfo &operator()(const string &filepath)
        {
            Cloud::FileUtil fu(filepath);
            Cloud::Config *config = Cloud::Config::GetInstance();
            if (fu.Exists() == false)
            {
                cout << "BackupInfo: file not exists" << endl;
                exit(-1);
            }
            pack_flag = false;
            packRunning = false;
            fsize = fu.FileSize();
            atime = fu.LastATime();
            mtime = fu.LastMTime();
            // realpath = config->GetBackDir() + fu.GetFileName();
            realpath = filepath;
            packpath = config->GetPackDir() + fu.GetFileName() + config->GetPackFileSuffix();
            url = config->GetDownLoadprefix() + fu.GetFileName();
            return *this;
        }

    public:
        bool pack_flag;   // 文件压缩标志
        bool packRunning; // 文件正在压缩中标志
        size_t fsize;     // 文件大小
        time_t atime;     // 最后一次访问时间
        time_t mtime;     // 最后一次修改时间
        string realpath;  // 文件实际存储路径
        string packpath;  // 压缩包存放路径
        string url;       // 下载文件url路径
    };
    class DataManger // 数据管理类
    {
    private:
        string backup_file;                            // 持久化存储文件
        std::unordered_map<string, BackupInfo> _table; // 建立url与备份信息映射表
        pthread_rwlock_t rwlock;                       // 定义一个读写锁
    public:
        DataManger()
        {
            backup_file = Cloud::Config::GetInstance()->GetBackUpFile();
            pthread_rwlock_init(&rwlock, nullptr);
            InitLoad();
        }
        ~DataManger()
        {
            pthread_rwlock_destroy(&rwlock);
        }
        bool InitLoad() // 初始化加载，加载之前的数据
        {
            string body;
            FileUtil fu(backup_file);
            if (fu.Exists() == false)
                return true;
            fu.GetCentent(&body);
            Json::Value root;
            JsonUtil::UnSerialize(body, &root);

            for (int i = 0; i < root.size(); i++)
            {
                BackupInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.packRunning = root[i]["packRunning"].asBool();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.fsize = root[i]["fsize"].asInt64();
                info.realpath = root[i]["realpath"].asString();
                info.packpath = root[i]["packpath"].asString();
                info.url = root[i]["url"].asString();
                Insert(info);
            }
            return true;
        }

        bool Storage() // 每次修改文件或新增文件都要进行持久化存储
        {
            // 1、读取数据
            vector<BackupInfo> array;
            GetAll(&array);
            // 2、对数据进行序列化
            Json::Value root;
            for (auto &e : array)
            {
                Json::Value item;
                // item["pack_flag"] = (Json::UInt64)e.pack_flag;
                // item["packRunning"] = (Json::UInt64)e.packRunning;
                // item["fsize"] = (Json::UInt64)e.fsize;
                // item["atime"] = (Json::UInt64)e.atime;
                // item["mtime"] = (Json::UInt64)e.mtime;
                item["pack_flag"] = (Json::Int64)e.pack_flag;
                item["packRunning"] = (Json::Int64)e.packRunning;
                item["fsize"] = (Json::Int64)e.fsize;
                item["atime"] = (Json::Int64)e.atime;
                item["mtime"] = (Json::Int64)e.mtime;

                item["realpath"] = e.realpath;
                item["packpath"] = e.packpath;
                item["url"] = e.url;
                root.append(item);
            }
            string body;
            JsonUtil::Serialize(root, &body);
            // 3、将数据写入文件
            FileUtil fu(backup_file);
            fu.SetCentent(body);
            return true;
        }
        bool Insert(const BackupInfo &info) // 新增文件
        {
            pthread_rwlock_wrlock(&rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&rwlock);
            Storage();
            return true;
        }
        bool Update(const BackupInfo &info) // 修改文件
        {
            pthread_rwlock_wrlock(&rwlock);
            _table[info.url] = info;
            pthread_rwlock_unlock(&rwlock);
            Storage();
            return true;
        }
        bool GetOneByUrl(const string &url, BackupInfo *info) // URL方式获取下载单个文件信息
        {
            pthread_rwlock_wrlock(&rwlock);
            if (_table.find(url) == _table.end())
            {
                pthread_rwlock_unlock(&rwlock);
                return false;
            }
            *info = _table[url];
            pthread_rwlock_unlock(&rwlock);
            return true;
        }
        bool GetOneByRealpath(const string &realpath, BackupInfo *info) // 真实路径获取一个备份信息
        {
            pthread_rwlock_wrlock(&rwlock);
            for (auto &e : _table)
            {
                if (e.second.realpath == realpath)
                {
                    *info = e.second;
                    pthread_rwlock_unlock(&rwlock);
                    return true;
                }
            }
            pthread_rwlock_unlock(&rwlock);
            return false;
        }
        bool GetAll(vector<BackupInfo> *array) // 获取所有文件的备份信息
        {
            pthread_rwlock_wrlock(&rwlock);
            for (auto &e : _table)
            {
                array->push_back(e.second);
            }
            pthread_rwlock_unlock(&rwlock);
            return true;
        }
    };
}

#endif